package bdck;
import java.time.LocalDate;  
import java.time.Month;  
import java.util.*;  


class Income {  
    private LocalDate date;  
    private double amount;  
    private String category;  
    private String note;  
  
    public Income(LocalDate date, double amount, String category, String note) {  
        this.date = date;  
        this.amount = amount;  
        this.category = category;  
        this.note = note;  
    }  
    public LocalDate getDate() { return date; }  
    public double getAmount() { return amount; }  
    public String getCategory() { return category; }  
    public String getNote() { return note; }  
  
    @Override  
    public String toString() {  
        return "Income{" +  
                "date=" + date +  
                ", amount=" + amount +  
                ", category='" + category + '\'' +  
                ", note='" + note + '\'' +  
                '}';  
    }  
}  ////
  
class Expense {  
    private LocalDate date;  
    private double amount;  
    private String category;  
    private String note;  
  
    public Expense(LocalDate date, double amount, String category, String note) {  
        this.date = date;  
        this.amount = amount;  
        this.category = category;  
        this.note = note;  
    }  
    public LocalDate getDate() { return date; }  
    public double getAmount() { return amount; }  
    public String getCategory() { return category; }  
    public String getNote() { return note; }  
  
    @Override  
    public String toString() {  
        return "Expense{" +  
                "date=" + date +  
                ", amount=" + amount +  
                ", category='" + category + '\'' +  
                ", note='" + note + '\'' +  
                '}';  
    }  
}  
  
public class Bill {  
  
	 private List<Income> incomes = new ArrayList<>();  
	    private List<Expense> expenses = new ArrayList<>();  
	    private double monthlyBudget;  
	    private Map<Month, Map<String, Double>> monthlyIncomeByCategory = new HashMap<>();  
	    private Map<Month, Map<String, Double>> monthlyExpenseByCategory = new HashMap<>();  
	    private Map<Month, Double> monthlyTotalIncome = new HashMap<>();  
	    private Map<Month, Double> monthlyTotalExpense = new HashMap<>();
    public Bill() {  
        this.monthlyBudget = 0;
        for (Month month : Month.values()) {  
            monthlyIncomeByCategory.put(month, new HashMap<>());  
            monthlyExpenseByCategory.put(month, new HashMap<>());  
            monthlyTotalIncome.put(month, 0.0);  
            monthlyTotalExpense.put(month, 0.0);  
        }  
    }
    public static void main(String[] args) {  
        Bill bill = new Bill();  
        Scanner scanner = new Scanner(System.in);  
  
        while (true) {  
        	System.out.println("欢迎使用个人账单管理系统");  
            System.out.println("1. 记录收入");  
            System.out.println("2. 记录支出");  
            System.out.println("3. 查看所有账单");  
            System.out.println("4. 查询账单");  
            System.out.println("5. 设置月度预算");  
            System.out.println("6. 查看月度统计");  
            System.out.println("7. 退出系统");  
            System.out.print("请输入选项序号: ");  
  
            int choice = scanner.nextInt();  
            scanner.nextLine();  
  
            switch (choice) {  
                case 1:  
                    bill.recordIncome(scanner);  
                    break;  
                case 2:  
                    bill.recordExpense(scanner);  
                    break;  
                case 3:  
                    bill.displayBills();  
                    break;  
                case 4:  
                    bill.queryBills(scanner);  
                    break;  
                case 5:  
                    bill.setMonthlyBudget(scanner);  
                    break;  
                case 6:  
                    bill.showMonthlyStatistics();  
                    break;  
                case 7:  
                    System.out.println("退出系统");  
                    return;  
                default:  
                    System.out.println("无效的选项，请重新输入。");  
            }  
        }  
    }  
  
    private void recordIncome(Scanner scanner) { 
    	System.out.println("请输入收入信息：");
        System.out.print("日期 (yyyy-MM-dd): ");  
        String dateStr = scanner.nextLine();  
        LocalDate date = LocalDate.parse(dateStr);  
  
       double amount;
        while (true) {  
            System.out.print("金额: ");  
            amount = scanner.nextDouble();  
            scanner.nextLine();  
            if (amount > 0) {  
                break;  
            } else {  
                System.out.println("金额必须为正数，请重新输入。");  
            }  
        }  
  
        System.out.print("类别 (如工资、奖金等): ");  
        String category = scanner.nextLine();  
  
        System.out.print("备注: ");  
        String note = scanner.nextLine();  
  
        Income income = new Income(date, amount, category, note);  
        incomes.add(income);  
        updateMonthlyStatistics(date, amount, category, true);  
        System.out.println("收入已成功录入！");  
    }  
  
    private void recordExpense(Scanner scanner) { 
    	System.out.println("请输入支出信息：");
        System.out.print("日期 (yyyy-MM-dd): ");  
        String dateStr = scanner.nextLine();  
        LocalDate date = LocalDate.parse(dateStr);  
  
        double amount;
        while (true) {  
            System.out.print("金额: ");  
            amount = scanner.nextDouble();  
            scanner.nextLine();  
            if (amount > 0) {  
                break;  
            } else {  
                System.out.println("金额必须为正数，请重新输入。");  
            }  
        }  
  
        System.out.print("类别 (如餐饮、交通、购物等): ");  
        String category = scanner.nextLine();  
  
        System.out.print("备注: ");  
        String note = scanner.nextLine();  
  
        if (amount > getRemainingBudget(date.getMonth())) {  
            System.out.println("支出超出预算！");  
            return;  
        }  
  
        Expense expense = new Expense(date, amount, category, note);  
        expenses.add(expense);  
        updateMonthlyStatistics(date, amount, category, false);  
        System.out.println("支出已成功记录！");  
    }  
  
  
    private void displayBills() {  
        System.out.println("收入记录:");  
        for (Income income : incomes) {  
            System.out.println(income);  
        }  
  
        System.out.println("支出记录:");  
        for (Expense expense : expenses) {  
            System.out.println(expense);  
        }  
    }  
  
    private void queryBills(Scanner scanner) {
        System.out.println("1. 按日期查询");
        System.out.println("2. 按日期范围查询");
        System.out.println("3. 按类别查询");
        System.out.print("请选择查询方式: ");
        int choice = scanner.nextInt();
        scanner.nextLine(); 
        switch (choice) {
            case 1:
                queryByDate(scanner);
                break;
            case 2:
                queryByDateRange(scanner);
                break;
            case 3:
                queryByCategory(scanner);
                break;
            default:
                System.out.println("无效的选项，请重新输入。");
        }
    }

    private void queryByDate(Scanner scanner) {
        System.out.print("请输入查询日期 (yyyy-MM-dd): ");
        String dateStr = scanner.nextLine();
        LocalDate date = LocalDate.parse(dateStr);

        System.out.println("收入记录:");
        for (Income income : incomes) {
            if (income.getDate().equals(date)) {
                System.out.println(income);
            }
        }

        System.out.println("\n支出记录:");
        for (Expense expense : expenses) {
            if (expense.getDate().equals(date)) {
                System.out.println(expense);
            }
        }
    }

    private void queryByDateRange(Scanner scanner) {
        System.out.print("请输入开始日期 (yyyy-MM-dd): ");
        String startDateStr = scanner.nextLine();
        LocalDate startDate = LocalDate.parse(startDateStr);

        System.out.print("请输入结束日期 (yyyy-MM-dd): ");
        String endDateStr = scanner.nextLine();
        LocalDate endDate = LocalDate.parse(endDateStr);

        System.out.println("收入记录:");
        for (Income income : incomes) {
            if (!income.getDate().isBefore(startDate) && !income.getDate().isAfter(endDate)) {
                System.out.println(income);
            }
        }

        System.out.println("\n支出记录:");
        for (Expense expense : expenses) {
            if (!expense.getDate().isBefore(startDate) && !expense.getDate().isAfter(endDate)) {
                System.out.println(expense);
            }
        }
    }

    private void queryByCategory(Scanner scanner) {
        System.out.print("请输入查询类别: ");
        String category = scanner.nextLine();

        System.out.println("收入记录:");
        for (Income income : incomes) {
            if (income.getCategory().equals(category)) {
                System.out.println(income);
            }
        }

        System.out.println("\n支出记录:");
        for (Expense expense : expenses) {
            if (expense.getCategory().equals(category)) {
                System.out.println(expense);
            }
        }
    }
    
    private void setMonthlyBudget(Scanner scanner) {  
        System.out.print("请输入月度预算: ");  
        this.monthlyBudget = scanner.nextDouble();  
        scanner.nextLine();  
        System.out.println("月度预算设置成功！");  
    }  
    
    private double getMonthlyTotalExpense(Month month) {  
        return monthlyTotalExpense.getOrDefault(month, 0.0);  
    }  
  
    private double getMonthlyTotalIncome(Month month) {  
        return monthlyTotalIncome.getOrDefault(month, 0.0);  
    }  
    private void updateMonthlyStatistics(LocalDate date, double amount, String category, boolean isIncome) {  
        Month month = date.getMonth();  
        Map<Month, Double> totalMap = isIncome ? monthlyTotalIncome : monthlyTotalExpense;  
        Map<Month, Map<String, Double>> categoryMap = isIncome ? monthlyIncomeByCategory : monthlyExpenseByCategory;  
  
        totalMap.put(month, totalMap.getOrDefault(month, 0.0) + amount);  
        categoryMap.get(month).put(category, categoryMap.get(month).getOrDefault(category, 0.0) + amount);  
    }  
    private double getRemainingBudget(Month month) {  
        return monthlyBudget - getMonthlyTotalExpense(month);  
    }  
    private void showMonthlyStatistics() {  
        Scanner scanner = new Scanner(System.in);  
        System.out.print("请输入要查询的月份 (如1代表一月, 2代表二月, ..., 12代表十二月): ");  
        int monthNum = scanner.nextInt();  
        Month month = Month.of(monthNum);  
        if (!monthlyTotalIncome.containsKey(month) || !monthlyTotalExpense.containsKey(month)) 
        {  
            System.out.println("无该月份的统计数据。");  
            return;  
        }  
        System.out.println("月度总收入: " + getMonthlyTotalIncome(month));  
        System.out.println("月度总支出: " + getMonthlyTotalExpense(month));  
        System.out.println("剩余预算: " + getRemainingBudget(month));  
  
        System.out.println("收入分类统计:");  
        for (Map.Entry<String, Double> entry : monthlyIncomeByCategory.get(month).entrySet()) {  
            System.out.println(entry.getKey() + ": " + entry.getValue());  
        }  
  
        System.out.println("支出分类统计:");  
        for (Map.Entry<String, Double> entry : monthlyExpenseByCategory.get(month).entrySet()) {  
            System.out.println(entry.getKey() + ": " + entry.getValue());  
        }    
    }
}
    